package GUIs;

import Graphics.FieldGraphics;
import Logic.Stone;
import HelperClasses.Constants;
import HelperClasses.GlobalFunctions;
import HelperClasses.Vektor;
import Logic.Result;
import Player.Player;
import java.awt.AWTEvent;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Point;

/*
 * mainGUI.java
 *
 * Created on 20. Mai 2008, 16:21
 */
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import javax.swing.JOptionPane;
import javax.swing.UIManager;

/**
 *
 * @author  johannes
 */
public class mainGUI extends javax.swing.JFrame {

    private int playersTurn = 0;
    private int end = 1;
    private FieldGraphics fg = new FieldGraphics(true);
    private boolean shotVectorFollow = true;
    private ArrayList<Stone> stones = new ArrayList<Stone>();
    private ArrayList<Player> Players = new ArrayList<Player>();
    private JHousePanel pnlHouse = new JHousePanel();
    private JFieldPanel pnlField = new JFieldPanel(pnlHouse);
    private boolean wButtonPressed = false;

    /** Creates new form mainGUI */
    public mainGUI() {
         //EventQueue einfügen, die Events vor den Listenern abfängt
        Toolkit.getDefaultToolkit().getSystemEventQueue().push(
                new EventQueue() {
                    protected void dispatchEvent(AWTEvent event) {
                        if (event instanceof KeyEvent) {
                            KeyEvent keyEvent = (KeyEvent) event;

                            // W
                            if ((keyEvent.getID() == KeyEvent.KEY_PRESSED) &&
                               ((keyEvent).getKeyCode() == KeyEvent.VK_W)) {
                                if(!wButtonPressed){
                                    wButtonPressed=true;
                                    System.out.println("W pressed");
                                }
                                
                            }
                            if ((keyEvent.getID() == KeyEvent.KEY_RELEASED) &&
                               ((keyEvent).getKeyCode() == KeyEvent.VK_W)) {
                                wButtonPressed=false;
                                System.out.println("W released");
                            }
                        }
                        super.dispatchEvent(event);
                    }
                });
                //
        try {
            //Tell the UIManager to use the platform look and feel
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
            //Do nothing
        }

        initComponents();

        setPreferredSize(new Dimension(1000, 650));
        java.awt.GridBagConstraints gridBagConstraints = new java.awt.GridBagConstraints();
        pnlDraw.setLayout(new java.awt.GridBagLayout());
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.5;
        gridBagConstraints.weighty = 0.5;
        pnlField.setFieldGraphics(fg);
        pnlDraw.add(pnlField, gridBagConstraints);
        pnlField.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {

            public void mouseMoved(java.awt.event.MouseEvent evt) {
                pnlFieldMouseMoved(evt);
            }
        });
        pnlField.addMouseListener(new java.awt.event.MouseAdapter() {

            public void mouseClicked(java.awt.event.MouseEvent evt) {
                pnlFieldMouseClicked(evt);
            }
        });

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.5;
        gridBagConstraints.weighty = 0.5;
        pnlHouse.setFieldGraphics(fg);
        pnlDraw.add(pnlHouse, gridBagConstraints);

        pack();
        Players.add(new Player("Spieler1", Color.RED));
        Players.add(new Player("Spieler2", Color.YELLOW));
        Players.get(0).setNumberNextStone(0);
        Players.get(1).setNumberNextStone(0);

        fg.setStones(stones);
        fg.setPlayer(new Point(50, 960));
        pnlField.repaint();

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;

        pnlStats = new javax.swing.JPanel();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTable1 = new javax.swing.JTable();
        pnlShotSettings = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        jSlider1 = new javax.swing.JSlider();
        jLabel4 = new javax.swing.JLabel();
        jSlider4 = new javax.swing.JSlider();
        pnlDraw = new javax.swing.JPanel();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Curling Game 0.1 by Markus and Johannes 2008-2009");
        getContentPane().setLayout(new java.awt.GridBagLayout());

        pnlStats.setBackground(new java.awt.Color(230, 230, 230));
        pnlStats.setPreferredSize(new java.awt.Dimension(200, 70));

        jScrollPane1.setMaximumSize(new java.awt.Dimension(200, 70));
        jScrollPane1.setMinimumSize(new java.awt.Dimension(200, 70));
        jScrollPane1.setPreferredSize(new java.awt.Dimension(200, 36));

        jTable1.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {null, null, null, null, null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null, null, null, null, null}
            },
            new String [] {
                "Spieler", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Ges."
            }
        ) {
            boolean[] canEdit = new boolean [] {
                false, false, false, false, false, false, false, false, false, false, false, true
            };

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        jTable1.setMaximumSize(new java.awt.Dimension(200, 36));
        jTable1.setMinimumSize(new java.awt.Dimension(200, 36));
        jTable1.setPreferredSize(new java.awt.Dimension(200, 36));
        jTable1.setShowVerticalLines(false);
        jScrollPane1.setViewportView(jTable1);

        javax.swing.GroupLayout pnlStatsLayout = new javax.swing.GroupLayout(pnlStats);
        pnlStats.setLayout(pnlStatsLayout);
        pnlStatsLayout.setHorizontalGroup(
            pnlStatsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 375, Short.MAX_VALUE)
            .addGroup(pnlStatsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(pnlStatsLayout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 406, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
        );
        pnlStatsLayout.setVerticalGroup(
            pnlStatsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 157, Short.MAX_VALUE)
            .addGroup(pnlStatsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(pnlStatsLayout.createSequentialGroup()
                    .addContainerGap()
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 68, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addContainerGap(78, Short.MAX_VALUE)))
        );

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.5;
        gridBagConstraints.weighty = 0.2;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        getContentPane().add(pnlStats, gridBagConstraints);

        pnlShotSettings.setBackground(new java.awt.Color(237, 237, 237));
        pnlShotSettings.setLayout(new java.awt.GridBagLayout());

        jLabel1.setText("Curling:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.insets = new java.awt.Insets(10, 10, 10, 10);
        pnlShotSettings.add(jLabel1, gridBagConstraints);

        jSlider1.setMaximum(50);
        jSlider1.setMinimum(-50);
        jSlider1.setValue(-20);
        jSlider1.setOpaque(false);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.insets = new java.awt.Insets(10, 10, 10, 10);
        pnlShotSettings.add(jSlider1, gridBagConstraints);

        jLabel4.setText("SimSpeed:");
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(10, 10, 10, 10);
        pnlShotSettings.add(jLabel4, gridBagConstraints);

        jSlider4.setMaximum(200);
        jSlider4.setValue(20);
        jSlider4.setOpaque(false);
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 1;
        gridBagConstraints.gridy = 3;
        gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTH;
        gridBagConstraints.weighty = 1.0;
        gridBagConstraints.insets = new java.awt.Insets(10, 10, 10, 10);
        pnlShotSettings.add(jSlider4, gridBagConstraints);

        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 2;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        gridBagConstraints.weightx = 0.5;
        gridBagConstraints.weighty = 0.8;
        gridBagConstraints.insets = new java.awt.Insets(4, 4, 4, 4);
        getContentPane().add(pnlShotSettings, gridBagConstraints);

        pnlDraw.setMinimumSize(new java.awt.Dimension(300, 400));
        pnlDraw.setPreferredSize(new java.awt.Dimension(400, 300));
        pnlDraw.setLayout(new java.awt.GridBagLayout());
        gridBagConstraints = new java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.gridheight = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
        getContentPane().add(pnlDraw, gridBagConstraints);

        pack();
    }// </editor-fold>//GEN-END:initComponents

   

    private void pnlFieldMouseClicked(java.awt.event.MouseEvent evt) {
        if (shotVectorFollow) {
            Runnable Animation = new Runnable() {

                public void run() {
                    //Stein erzeugen
                    fg.setShotVector(new Vektor(fg.getShotVector().getX() * Constants.directionSliderMultiplier, fg.getShotVector().getY() * Constants.strenghtSliderMulitplier));

                    double strength = fg.getShotVector().getY();
                    double direction = fg.getShotVector().getX();
                    double curling = jSlider1.getValue();

                    // randomize (Spielerstärke...)
//                    System.out.println("strength1: " + strength);
//                    System.out.println("ranfak: " + Players.get(playersTurn).getRandomFactor());
                    double value = Math.random() * Players.get(playersTurn).getRandomFactor();
                    strength = strength * (1 + (value / 2 - value));
//                    System.out.println("strength2: " + strength);


                    stones.add(new Stone(50, 1000, Players.get(playersTurn)));
                    Players.get(playersTurn).setNumberNextStone(Players.get(playersTurn).getNumberNextStone() + 1);
                    playersTurn = (playersTurn + 1) % 2;

                    stones.get(stones.size() - 1).setImpuls(new Vektor(direction, strength));
                    stones.get(stones.size() - 1).setCurling(curling);
                    stones.get(stones.size() - 1).setPos(new Point(50, 1000));
                    shotVectorFollow = false;

                    //Steinanimation
                    while (true) {
                        try {
                            Thread.sleep(jSlider4.getValue());
                        } catch (InterruptedException ex) {
                        }
                        //alle Steine bewegen
                        boolean noonemoving = true;
                        for (Stone s : stones) {
                            if (s.isMoving() && s.isInGame()) {
                                s.move();
                                if (s.slowdown()) {
                                    // beenden wenn sich keiner mehr bewegt
                                    noonemoving = false;
                                }
                                if (s.checkOutOfBounds()) {
                                    System.out.println("draußen");
                                    pnlField.repaint();
                                }
                            }
                        }
                        if (noonemoving) {
                            shotVectorFollow = true;

                            // Spielstand ausgeben
                            System.out.println("Player 1: " + Result.getPoints(Players.get(0), stones) + " Steine");
                            System.out.println("Player 2: " + Result.getPoints(Players.get(1), stones) + " Steine");
                            break;
                        }
                        //Kollision testen
                        for (int i = 0; i < stones.size(); i++) {
                            for (int j = 0; j < stones.size(); j++) {
                                if (!stones.get(i).isMoving() && stones.get(j).isMoving()) {
                                    if (GlobalFunctions.pointDistance(stones.get(i).getPos(), stones.get(j).getPos()) < 16) {
//                                        System.out.println("kollision");
                                        //länge des impulsvektors
                                        Stone movingStone = stones.get(j);
                                        Stone pwnedStone = stones.get(i);
                                        pwnedStone.setIsMoving(true);
                                        double speed = Math.sqrt(Math.pow(movingStone.getImpuls().getX(), 2) + Math.pow(movingStone.getImpuls().getY(), 2));
//                                        System.out.println(String.valueOf(speed));
                                        //Richtungsvektor moving
                                        Vektor u = new Vektor(movingStone.getImpuls().getX(), movingStone.getImpuls().getY());
                                        //Verbindungsvektor mittelpunkte
                                        Vektor v = new Vektor(pwnedStone.getPosVek().getX() - movingStone.getPosVek().getX(), pwnedStone.getPosVek().getY() - movingStone.getPosVek().getY());
                                        //u=new Vektor(5,10);
                                        //v=new Vektor(-5,5);        
                                        double alpha = Math.acos(Math.abs(u.multiply(v)) / (u.getLength() * v.getLength()));
                                        double vlength = Math.cos(alpha) * u.getLength();
                                        double factor = vlength / v.getLength();
                                        v.enlarge(factor);
                                        Vektor w = new Vektor(u.getX() - v.getX(), u.getY() - v.getY());
                                        v.enlarge(0.8); //nicht die gesamte energie wird übernommen
                                        w.enlarge(0.8);
                                        pwnedStone.setImpuls(new Vektor(v.getX(), v.getY()));
                                        movingStone.setImpuls(new Vektor(w.getX(), w.getY()));
//                                        System.out.println("alpha:" + alpha);
//                                        System.out.println("ux:" + u.getX());
//                                        System.out.println("uY:" + u.getY());
//                                        System.out.println("vx:" + v.getX());
//                                        System.out.println("vY:" + v.getY());
//                                        System.out.println("wx:" + w.getX());
//                                        System.out.println("wY:" + w.getY());
                                    //Vector<Double> w=new Vector<Double>();

                                    }
                                }
                            }
                        }

                        pnlField.repaint();
                    }


                    // End zu Ende?
                    if (Players.get(0).getNumberNextStone() == Constants.numberStonesInEnd && Players.get(1).getNumberNextStone() == Constants.numberStonesInEnd) {
                        JOptionPane.showMessageDialog(null, String.format("End %s beendet.", end));

                        // in JTable, Punkte merken
                        int aPoints = Result.getPoints(Players.get(0), stones);
                        int bPoints = Result.getPoints(Players.get(1), stones);
                        Players.get(0).points += aPoints;
                        Players.get(1).points += bPoints;

                        jTable1.setValueAt(aPoints, 0, end);
                        jTable1.setValueAt(bPoints, 1, end);
                        // gesamt
                        jTable1.setValueAt(Players.get(0).points, 0, 11);
                        jTable1.setValueAt(Players.get(1).points, 1, 11);

                        Players.get(0).setNumberNextStone(0);
                        Players.get(1).setNumberNextStone(0);
                        stones = new ArrayList<Stone>();
                        fg.setStones(stones);
                        playersTurn = playersTurn++ % 2;
                        end++;
                    }

                    // Spiel zuende?
                    if (end > 10) {
                        if (Players.get(0).points == Players.get(1).points) {
                            JOptionPane.showMessageDialog(null, "Unentschieden.");
                        } else {
                            if (Players.get(0).points > Players.get(1).points) {
                                JOptionPane.showMessageDialog(null, String.format("%s hat gewonnen.", Players.get(0).getName()));
                            } else {
                                JOptionPane.showMessageDialog(null, String.format("%s hat gewonnen.", Players.get(1).getName()));
                            }
                        }
                        System.exit(0);
                    }
                    pnlField.repaint();
                }
            };
            new Thread(Animation).start();
        }
    }

    private void pnlFieldMouseMoved(java.awt.event.MouseEvent evt) {
        if (shotVectorFollow) {
            int pnlFieldHeight = pnlField.getHeight();
            int pnlFieldWidth = pnlField.getWidth();
            Dimension fieldsize = GlobalFunctions.getScaledDimension(100, 1000, pnlFieldWidth, pnlFieldHeight);
            Point MousePos = evt.getPoint();
            if (MousePos.getX() < (pnlFieldWidth / 2 + fieldsize.width / 2) && MousePos.getX() > (pnlFieldWidth / 2 - fieldsize.width / 2)) {
                double direction = ((MousePos.getX() - pnlFieldWidth / 2) * 100 / fieldsize.width);
                double strength = (pnlFieldHeight - MousePos.getY()) * 1000 / pnlFieldHeight;
                fg.setShotVector(new Vektor(direction, -strength));
                pnlField.repaint();
            }
        //shotvector folgt im gesamten panel
            /*else if(MousePos.getX()>=(pnlFieldWidth/2+fieldsize.width/2)){
        double direction=50;
        double strength=(pnlFieldHeight-MousePos.getY())*1000/pnlFieldHeight;
        fg.setShotVector(new Vektor(direction, -strength));
        pnlField.repaint();
        
        }else if(MousePos.getX()<=(pnlFieldWidth/2-fieldsize.width/2)){
        double direction=-50;
        double strength=(pnlFieldHeight-MousePos.getY())*1000/pnlFieldHeight;
        fg.setShotVector(new Vektor(direction, -strength));
        pnlField.repaint();
        }*/

        }
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new mainGUI().setVisible(true);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JSlider jSlider1;
    private javax.swing.JSlider jSlider4;
    private javax.swing.JTable jTable1;
    private javax.swing.JPanel pnlDraw;
    private javax.swing.JPanel pnlShotSettings;
    private javax.swing.JPanel pnlStats;
    // End of variables declaration//GEN-END:variables
}
